use std::ops::{Deref, DerefMut};
use axum::Router;
use req::handler;
use serde::{Deserialize, Serialize};
use tokio::net::TcpListener;
use tower_http::services::ServeDir;

use crate::{config::{HTML_DIR, HTTP_ADDR_V4}, error::AppErr};


mod req;
mod res;
mod api;
mod client;


pub async fn run() -> Result<(), AppErr> {

    handler::init();

    let serve_dir = ServeDir::new(HTML_DIR)
        .append_index_html_on_directories(true);

    let app = Router::new()
        .nest_service("/web", serve_dir)    
        .nest("/api", api::register())
    ;   
    println!("http server:{}", HTTP_ADDR_V4);

    let listener = TcpListener::bind(HTTP_ADDR_V4).await?;
    axum::serve(listener, app).await?;

    Ok(())
}



#[derive(Debug, Serialize, Deserialize)]
#[repr(transparent)]
pub struct Cbor<T>(pub T);

impl<T> Deref for Cbor<T> {

    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> DerefMut for Cbor<T> {

    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

mod header {
    use axum::http::HeaderValue;


    pub const DEVICE_TOKEN: &'static str = "device_token";


    pub const API_RESP: &'static str = "resp";
    pub const VAL_API_OK: HeaderValue = HeaderValue::from_static("ok");
    pub const VAL_API_ERR: HeaderValue = HeaderValue::from_static("err");
    pub const VAL_API_PANIC: HeaderValue = HeaderValue::from_static("panic");


    pub const MSG_SEQ: &'static str = "msg_seq";
    pub const MSG_TYPE: &'static str = "msg_type";
    pub const MSG_CMD: &'static str = "msg_cmd";
}

